<?php

/**
 * This is the model class for table "users".
 *
 * The followings are the available columns in table 'users':
 * @property integer $user_id
 * @property string $username
 * @property string $email
 * @property string $password
 * @property string $salt
 * @property string $display_name
 * @property string $activation_key
 * @property string $type
 * @property integer $status
 * @property integer $joined
 * @property string $first_name
 * @property string $last_name
 * @property string $gender
 * @property string $social_provider
 * @property string $social_uid
 * @property string $access_token
 * @property string $bio
 * @property integer $last_login_time
 * @property string $last_login_ip
 * @property string $country
 * @property string $state
 * @property string $city
 * @property string $address
 * @property string $phone
 * @property string $telephone
 * @property string $mobile
 * @property string $postcode
 * @property integer $featured
 * @property string $avatar
 * @property string $webpage
 * @property string $timezone
 * @property string $language
 * @property string $uploaded_size
 * 
 * The followings are the available model relations:
 * @property Posts[] $posts
 */
class User extends CActiveRecord {

    /**
     * hold the password after find
     * @var string
     */
    public $initialPassword;

    /**
     * password required when change or create new
     * @var string
     */
    public $repassword;
    public $re_email;

    const STATUS_WAITING_ACTIVE = 0;
    const STATUS_ACTIVE = 1;
    const STATUS_SUSPENDED = 2;
    const GENDER_FEMALE = 'female';
    const GENDER_MALE = 'male';

    /**
     * define user type
     */
    const TYPE_SUPER_ADMIN = 'supperAdmin';
    const TYPE_ADMIN = 'admin';
    const TYPE_MEMBER = '';

    /**
     * Returns the static model of the specified AR class.
     * @param string $className active record class name.
     * @return User the static model class
     */
    public static function model($className = __CLASS__) {
	return parent::model($className);
    }

    /**
     * @return string the associated database table name
     */
    public function tableName() {
	return '{{users}}';
    }

    /**
     * @return array validation rules for model attributes.
     */
    public function rules() {
// NOTE: you should only define rules for those attributes that
// will receive user inputs.
	return array(
	    array('username, first_name, last_name, email', 'required', 'on' => 'insert'),
	    array('password', 'required', 'on' => 'insert'),
	    array('re_email', 'compare', 'compareAttribute' => 'email', 'on' => 'insert', 'message' => 'The emails do not match. Please try again'),
	    array('repassword', 'compare', 'compareAttribute' => 'password', 'on' => 'insert, edit', 'message' => 'The passwords do not match. Please try again.'),
	    array('username, email', 'unique'),
	    array('email', 'email'),
	    array('gender', 'in', 'range' => array(self::GENDER_FEMALE, self::GENDER_MALE)),
	    array('user_id, status, joined, last_login_time, featured', 'numerical', 'integerOnly' => true),
	    array('email, password, salt, display_name, activation_key', 'length', 'max' => 128),
	    array('type, first_name, last_name, social_provider, last_login_ip, username', 'length', 'max' => 25),
	    array('gender', 'length', 'max' => 6),
	    array('social_uid, access_token, address, avatar, webpage', 'length', 'max' => 255),
	    array('country, state, city, telephone, mobile, timezone', 'length', 'max' => 45),
	    array('phone, postcode', 'length', 'max' => 15),
	    array('postcode', 'checkCountry', 'on' => 'insert, update'),
	    array('language', 'length', 'max' => 10),
	    array('birthdate, bio, uploaded_size', 'safe'),
	    // The following rule is used by search().
// Please remove those attributes that should not be searched.
	    array('user_id, email, password, salt, display_name, type, status, joined, first_name, last_name, gender, social_provider, social_uid, access_token, bio, country, state, city, address, phone, telephone, mobile, postcode, webpage, language', 'safe', 'on' => 'search'),
	);
    }

    public function checkCountry($attribute, $params) {
	if ($this->{$attribute} == '' && $this->country == 'US') {
	    $this->addError($attribute, 'Zip Code cannot be blank.');
	}
    }

//public function check_minprice($attribute, $params){ 
//        if (!$this->hasErrors()) { 
//            if ($this->{$attribute} <= 0) { 
//                $this->addError($attribute, 'Min price more than 0'); 
//            } 
//        } 
//    }
    /**
     * @return array relational rules.
     */
    public function relations() {
// NOTE: you may need to adjust the relation name and the related
// class name for the relations automatically generated below.
	return array(
	    'posts' => array(self::HAS_MANY, 'Posts', 'author_id'),
	);
    }

    /**
     * @return array customized attribute labels (name=>label)
     */
    public function attributeLabels() {
	return array(
	    'user_id' => 'ID',
	    'username' => 'Username',
	    'email' => 'Email',
	    'password' => 'Password',
	    'repassword' => 'Re-Password',
	    'salt' => 'Salt',
	    'display_name' => 'Display Name',
	    'activation_key' => 'Activation Key',
	    'type' => 'Type',
	    'status' => 'Status',
	    'joined' => 'Joined',
	    'first_name' => 'First Name',
	    'last_name' => 'Last Name',
	    'gender' => 'Gender',
	    'social_provider' => 'Social Provider',
	    'social_uid' => 'Social Uid',
	    'access_token' => 'Access Token',
	    'bio' => 'Bio',
	    'last_login_time' => 'Last Login Time',
	    'last_login_ip' => 'Last Login Ip',
	    'country' => 'Country',
	    'state' => 'State',
	    'city' => 'City',
	    'address' => 'Address',
	    'phone' => 'Phone',
	    'telephone' => 'Telephone',
	    'mobile' => 'Mobile',
	    'Zip Code' => 'Postcode',
	    'featured' => 'Featured',
	    'avatar' => 'Avatar',
	    'webpage' => 'Webpage',
	    'timezone' => 'Timezone',
	    'language' => 'Language',
	);
    }

    /**
     * Retrieves a list of models based on the current search/filter conditions. for admin
     * @return CActiveDataProvider the data provider that can return the models based on the search/filter conditions.
     */
    public function search() {

	$criteria = new CDbCriteria;
	$criteria->compare('email', $this->email, true);
	$criteria->compare('username', $this->username, true);
	return new CActiveDataProvider($this, array(
	    'criteria' => $criteria,
	    'pagination' => array(
		'pageSize' => param('pageSize')
	    ),
	    'sort' => array(
		'defaultOrder' => array(
		    'user_id' => CSort::SORT_DESC
		),
	    ),
	));
    }

    /**
     * Retrieves a list of models based on the current search/filter conditions. for user
     * @return CActiveDataProvider the data provider that can return the models based on the search/filter conditions.
     */
    public function searchMember($id, $search) {

	$criteria = new CDbCriteria;
	if ($search) {
	    $criteria->addCondition('user_id != ' . $id);
	    $criteria->addCondition('status=' . User::STATUS_ACTIVE);
	    $criteria->compare('email', $this->email, true);
	    $criteria->compare('username', $this->username, true);
	    $criteria->addCondition('type != "admin"');
	} else {
	    $criteria->addCondition('type != "admin" and type != ""');
	}
	return new CActiveDataProvider($this, array(
	    'criteria' => $criteria,
	    'pagination' => array(
		'pageSize' => param('pageSize')
	    ),
	    'sort' => array(
		'defaultOrder' => array(
		    'user_id' => CSort::SORT_DESC
		),
	    ),
	));
    }

    public function beforeValidate() {
	parent::beforeValidate();
	if ($this->postcode == '' && $this->country == 'US') {
	    $this->addError('postcode', 'Zip Code cannot be blank.');
	}

	return true;
    }

    /**
     * before save check is new user then update user register date
     * @return boolean
     */
    public function beforeSave() {
	if (parent::beforeSave()) {
	    if ($this->isNewRecord) {
		$this->joined = time();

//check
		if ($this->scenario == 'insert') {
//create random salt
		    $this->salt = $this->__generateSalt();
		}
	    } else {
		
	    }

// in this case, we will use the old hashed password.
	    if (empty($this->password) && empty($this->repassword) && !empty($this->initialPassword))
		$this->password = $this->repassword = $this->initialPassword;
	    else
		$this->password = $this->hashPassword($this->password, $this->salt);

	    return TRUE;
	}
	return FALSE;
    }

    /**
     * action after save
     */
    public function afterSave() {
	parent::afterSave();

//reset the password
	$this->password = $this->repassword = NULL;
    }

    /**
     * action after find result
     */
    public function afterFind() {
//reset the password to null because we don't want the hash to be shown.
	$this->initialPassword = $this->password;
	$this->password = null;

	parent::afterFind();
    }

    /**
     * Checks if the given password is correct.
     * @param string the password to be validated
     * @return boolean whether the password is valid
     */
    public function validatePassword($password) {
	return $this->hashPassword($password, $this->salt) === $this->initialPassword;
    }

    /**
     * Generates the password hash.
     * @param string password
     * @param string salt
     * @return string hash
     */
    public function hashPassword($password, $salt) {
	return md5($salt . $password);
    }

    /**
     * Generates a salt that can be used to generate a password hash.
     * @return string the salt
     */
    protected function __generateSalt() {
	return uniqid('', true);
    }

    /**
     * get text of status
     * @return string
     */
    public function getStatusText() {
	switch ($this->status) {
	    case self::STATUS_ACTIVE :
		$return = 'Actived';
		break;
	    case self::STATUS_SUSPENDED :
		$return = 'Suspended';
		break;
	    case self::STATUS_WAITING_ACTIVE :
		$return = 'Waiting to active';
		break;
	    default :
		$return = 'Undefined';
		break;
	}

	return $return;
    }

    /**
     * get range status allow
     * @return array $status_key => $text
     */
    public static function getStatusRange() {
	return array(
	    self::STATUS_WAITING_ACTIVE => 'Waiting Active',
	    self::STATUS_ACTIVE => 'Active',
	    self::STATUS_SUSPENDED => 'Suspended'
	);
    }

    /**
     * get type of current user
     */
    public function getType() {
	
    }

    /**
     * get avatar url of current user
     * allow size: small, thumb, medium, large, full
     * if user is logon with social provider, return url of social provider
     * @param string $size small, thumbnail, medium, large, full
     */
    public function getAvatarUrl($size = 'thumb') {
	switch ($size) {
	    case 'thumb' :
		$width = 200;
		$height = 150;
		break;
	    case 'small' :
		$width = 64;
		$height = 64;
		break;
	    default :
		$width = 800;
		$height = 600;
		break;
	}

	if ($this->avatar == '' && $this->social_provider == '') {
//empty
	    $avatar = 'default.png';
	} else {
	    $avatar = $this->avatar;
	}

	return ImageHelper::thumb($width, $height, 'avatar' . DIRECTORY_SEPARATOR . $avatar);
    }

    /**
     * get range of gender
     * @return array key => value
     */
    public static function getGenderRange() {
	return array(
	    self::GENDER_MALE => 'Male',
	    self::GENDER_FEMALE => 'Female'
	);
    }

    /**
     *
     * @return type
     */
    public static function getTypeRange() {
	return array(
	    self::TYPE_MEMBER => 'Member',
	    self::TYPE_ADMIN => 'Admin',
//	    self::TYPE_SUPER_ADMIN => 'Super Admin'
	);
    }

    /**
     * approve user
     */
    public static function approveUser($id) {
	db()->createCommand('UPDATE {{users}} SET status=' . User::STATUS_ACTIVE . ' WHERE user_id=' . $id)->execute();
    }

    /**
     * check whether user is friend and check whether user sended request
     * @param type $userId
     * @param type $displayName
     * @return type
     */
    public function checkFriend($selfId, $userIdReceive, $displayName = '') {
	$aFriends = Friend::getIdsFriend($selfId);
	$aIdFriendRequested = FriendRequest::getIdsSendTo($selfId);

	if (array_search($userIdReceive, $aFriends) !== false) {
// return '<img alt="chat" title="Chat" class="chat-with chat-in-dis" src="' . WWW_URL . 'img/chat-with.png" id-user="' . $userId . '" user-name="' . substr($displayName, 0, 10) . '"/>';
	    return '';
	} else {
	    if (array_search($userIdReceive, $aIdFriendRequested) !== false) {
		return '';
	    } else {
		return '<img alt="add friend" title="Add friend" class="add-friend invite-id-' . $userIdReceive . '" user-receive="' . $userIdReceive . '" src="' . WWW_URL . 'img/addfriend.png"/>';
	    }
	}
    }

    /**
     * get display name of user
     */
    public function getDisplayName() {
	return "<a href='" . SITE_NAME_URL . "user/" . $this->user_id . "'>" . $this->username . "</a>";
    }

    /**
     * get email of user
     */
    public function getEmail() {
	return "<a href='" . SITE_NAME_URL . "user/" . $this->user_id . "'>" . $this->email . "</a>";
    }

    /**
     * get list email of user for blockingu
     */
    public static function getListEmail($idUser, $email) {
	//get list of users was blocked
	$aIdsBlocked = BlockMessage::getIdsBlock($idUser);
	$sId = $idUser;
	if ($aIdsBlocked) {
	    foreach ($aIdsBlocked as $item) {
		$sId .= ',' . $item;
	    }
	}
	$emails = db()->createCommand('SELECT email, user_id FROM {{users}} WHERE
					user_id NOT IN (' . $sId . ' )
					AND (email like "%' . $email . '" or email like "%' . $email . '%" or email like "' . $email . '%")')->queryAll();
	return $emails;
    }

    public function afterDelete() {
	parent::afterDelete();
	//delete posts
	$aPosts = db()->createCommand('SELECT post_id FROM {{posts}} WHERE user_id = ' . $this->user_id)->queryAll();
	foreach ($aPosts as $post) {
	    Posts::model()->findByPk($post['post_id'])->delete();
	}

	//delete request
	db()->createCommand('DELETE FROM {{friend_requests}} WHERE user_send=' . $this->user_id . ' and user_receive=' . $this->user_id)->execute();
	//delete friend
	db()->createCommand('DELETE FROM {{friends}} WHERE user_id=' . $this->user_id . ' and friend_user_id=' . $this->user_id)->execute();
    }

}

